home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / polygons.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  38.9 KB  |  1,546 lines

  1. /* polygons.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: polygons.c,v 1.34 1995/11/30 00:21:55 brianp Exp $
  26.  
  27. $Log: polygons.c,v $
  28.  * Revision 1.34  1995/11/30  00:21:55  brianp
  29.  * restored old gl_polygon_edge function
  30.  *
  31.  * Revision 1.33  1995/11/14  21:49:40  brianp
  32.  * optimized polygon rendering setup
  33.  *
  34.  * Revision 1.32  1995/11/04  20:09:07  brianp
  35.  * optimized gl_polygon_edge()
  36.  *
  37.  * Revision 1.31  1995/10/29  19:14:44  brianp
  38.  * added glPolygonOffsetEXT display list support
  39.  *
  40.  * Revision 1.30  1995/10/27  20:30:29  brianp
  41.  * added glPolygonOffsetEXT()
  42.  *
  43.  * Revision 1.29  1995/10/24  20:52:15  brianp
  44.  * renamed COMPUTE_PLANE_Z as gl_compute_z
  45.  * renamed polygon_edge as gl_polygon_edge
  46.  * use new color interpolation based on fixed point arithmetic
  47.  * removed dead code
  48.  *
  49.  * Revision 1.28  1995/10/22  21:20:50  brianp
  50.  * changed 0.5 to 0.5F in COMPUTE_PLANE_Z calls
  51.  *
  52.  * Revision 1.27  1995/10/22  20:29:37  brianp
  53.  * removed dead code
  54.  *
  55.  * Revision 1.26  1995/10/19  15:48:28  brianp
  56.  * added gamma support
  57.  * changed DD.color arguments to GLubytes
  58.  *
  59.  * Revision 1.25  1995/10/17  21:40:04  brianp
  60.  * added fast_flat_rgba_z_polygon() function
  61.  * removed fast_ci/rgb_polygon() functions
  62.  *
  63.  * Revision 1.24  1995/09/20  18:20:39  brianp
  64.  * prototype device driver changes described
  65.  *
  66.  * Revision 1.23  1995/09/13  14:51:05  brianp
  67.  * use CC.NewState convention
  68.  * use DEFARRAY/UNDEFARRAY macros for Mac
  69.  * replaced VB.Vs and VB.Vt with VB.TexCoord
  70.  *
  71.  * Revision 1.22  1995/07/28  21:34:16  brianp
  72.  * support polygons draw in viewport larger than window
  73.  *
  74.  * Revision 1.21  1995/07/15  14:04:50  brianp
  75.  * fixed texture coord interpolation bug
  76.  *
  77.  * Revision 1.20  1995/07/11  17:47:45  brianp
  78.  * round window coords to nearest int, not truncate, in fast_ci|rgba_polygon
  79.  *
  80.  * Revision 1.19  1995/06/20  16:32:40  brianp
  81.  * new depth buffer value computations
  82.  * introduced new triangle rasterizer code, experimental, not used yet
  83.  *
  84.  * Revision 1.18  1995/06/12  15:43:35  brianp
  85.  * changed color arrays to GLubyte
  86.  * new interpolation functions
  87.  *
  88.  * Revision 1.17  1995/06/05  20:27:53  brianp
  89.  * added CC.Polygon.Unfilled stuff
  90.  *
  91.  * Revision 1.16  1995/06/02  13:59:46  brianp
  92.  * added fast_smooth_rgba_z_polygon() function
  93.  *
  94.  * Revision 1.15  1995/05/31  19:34:12  brianp
  95.  * replaced MAX_VERTICES with VB_MAX
  96.  *
  97.  * Revision 1.14  1995/05/22  21:02:41  brianp
  98.  * Release 1.2
  99.  *
  100.  * Revision 1.13  1995/05/12  17:01:05  brianp
  101.  * changed CC.Mode!=0 to INSIDE_BEGIN_END
  102.  *
  103.  * Revision 1.12  1995/04/18  15:48:23  brianp
  104.  * fixed assignment of NULL to function pointers to prevent warnings on Suns
  105.  *
  106.  * Revision 1.11  1995/04/12  15:36:15  brianp
  107.  * updated to use DD.draw_* function pointers
  108.  *
  109.  * Revision 1.10  1995/03/27  20:31:53  brianp
  110.  * new Texture.Enabled scheme
  111.  *
  112.  * Revision 1.9  1995/03/24  19:28:13  brianp
  113.  * introduced VB
  114.  *
  115.  * Revision 1.8  1995/03/07  14:20:59  brianp
  116.  * updated for new XSetForeground/GC scheme
  117.  *
  118.  * Revision 1.7  1995/03/04  19:29:44  brianp
  119.  * 1.1 beta revision
  120.  *
  121.  * Revision 1.6  1995/03/02  19:18:54  brianp
  122.  * new RasterMask logic
  123.  * fixed Vcolor/Vbcolor bug in textured_polygon()
  124.  *
  125.  * Revision 1.5  1995/02/27  22:49:01  brianp
  126.  * modified for PB
  127.  *
  128.  * Revision 1.4  1995/02/27  15:08:17  brianp
  129.  * added Vcolor/Vindex scheme
  130.  *
  131.  * Revision 1.3  1995/02/26  22:58:57  brianp
  132.  * made COMPUTE_PLANE_Z a function w/ FP overflow checking
  133.  *
  134.  * Revision 1.2  1995/02/25  22:07:43  brianp
  135.  * more debugging code
  136.  *
  137.  * Revision 1.1  1995/02/24  14:26:49  brianp
  138.  * Initial revision
  139.  *
  140.  */
  141.  
  142.  
  143. #include <string.h>
  144. #include "context.h"
  145. #include "dd.h"
  146. #include "feedback.h"
  147. #include "gamma.h"
  148. #include "interp.h"
  149. #include "lines.h"
  150. #include "list.h"
  151. #include "macros.h"
  152. #include "points.h"
  153. #include "span.h"
  154. #include "vb.h"
  155.  
  156. /*#include "triangle.h"*/
  157.  
  158.  
  159. void glCullFace( GLenum mode )
  160. {
  161.    if (CC.CompileFlag) {
  162.       gl_save_cullface( mode );
  163.    }
  164.    if (CC.ExecuteFlag) {
  165.       if (mode!=GL_FRONT && mode!=GL_BACK) {
  166.      gl_error( GL_INVALID_ENUM, "glCullFace" );
  167.      return;
  168.       }
  169.       if (INSIDE_BEGIN_END) {
  170.      gl_error( GL_INVALID_OPERATION, "glCullFace" );
  171.      return;
  172.       }
  173.       CC.Polygon.CullFaceMode = mode;
  174.       CC.NewState = GL_TRUE;
  175.    }
  176. }
  177.  
  178.  
  179.  
  180. void glFrontFace( GLenum mode )
  181. {
  182.    if (CC.CompileFlag) {
  183.       gl_save_frontface( mode );
  184.    }
  185.    if (CC.ExecuteFlag) {
  186.       if (INSIDE_BEGIN_END) {
  187.      gl_error( GL_INVALID_OPERATION, "glFrontFace" );
  188.      return;
  189.       }
  190.       if (mode!=GL_CW && mode!=GL_CCW) {
  191.      gl_error( GL_INVALID_ENUM, "glFrontFace" );
  192.      return;
  193.       }
  194.       CC.Polygon.FrontFace = mode;
  195.    }  
  196. }
  197.  
  198.  
  199.  
  200. void glPolygonMode( GLenum face, GLenum mode )
  201. {
  202.    if (CC.CompileFlag) {
  203.       gl_save_polygonmode( face, mode );
  204.    }
  205.    if (CC.ExecuteFlag) {
  206.       if (INSIDE_BEGIN_END) {
  207.      gl_error( GL_INVALID_OPERATION, "glPolygonMode" );
  208.      return;
  209.       }
  210.       if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) {
  211.      gl_error( GL_INVALID_ENUM, "glPolygonMode(face)" );
  212.      return;
  213.       }
  214.       else if (mode!=GL_POINT && mode!=GL_LINE && mode!=GL_FILL) {
  215.      gl_error( GL_INVALID_ENUM, "glPolygonMode(mode)" );
  216.      return;
  217.       }
  218.  
  219.       if (face==GL_FRONT || face==GL_FRONT_AND_BACK) {
  220.      CC.Polygon.FrontMode = mode;
  221.       }
  222.       if (face==GL_BACK || face==GL_FRONT_AND_BACK) {
  223.      CC.Polygon.BackMode = mode;
  224.       }
  225.  
  226.       /* Compute a handy "shortcut" value: */
  227.       if (CC.Polygon.FrontMode!=GL_FILL || CC.Polygon.BackMode!=GL_FILL) {
  228.      CC.Polygon.Unfilled = GL_TRUE;
  229.       }
  230.       else {
  231.      CC.Polygon.Unfilled = GL_FALSE;
  232.       }
  233.  
  234.       CC.NewState = GL_TRUE;
  235.    }
  236. }
  237.  
  238.  
  239.  
  240. void glPolygonStipple( const GLubyte *mask )
  241. {
  242.    if (CC.CompileFlag) {
  243.       /*gl_save_polygon_stipple( mask );*/
  244.    }
  245.    if (CC.ExecuteFlag) {
  246.       /* TODO:  bit twiddling, unpacking */
  247.       if (INSIDE_BEGIN_END) {
  248.      gl_error( GL_INVALID_OPERATION, "glPolygonStipple" );
  249.      return;
  250.       }
  251.       MEMCPY( CC.PolygonStipple, mask, 32*sizeof(GLuint) );
  252.    }
  253. }
  254.  
  255.  
  256.  
  257. void glGetPolygonStipple( GLubyte *mask )
  258. {
  259.    /* TODO */
  260. }
  261.  
  262.  
  263.  
  264. void glPolygonOffsetEXT( GLfloat factor, GLfloat bias )
  265. {
  266.    if (CC.CompileFlag) {
  267.       gl_save_polygonoffset( factor, bias );
  268.    }
  269.    if (CC.ExecuteFlag) {
  270.       if (INSIDE_BEGIN_END) {
  271.          gl_error( GL_INVALID_OPERATION, "glPolygonOffsetEXT" );
  272.          return;
  273.       }
  274.       CC.Polygon.OffsetFactor = factor;
  275.       CC.Polygon.OffsetBias = bias;
  276.    }
  277. }
  278.  
  279.  
  280.  
  281. /**********************************************************************/
  282. /*****                    Rasterization                           *****/
  283. /**********************************************************************/
  284.  
  285.  
  286. /*
  287.  * Summary of polygon drawing functions:
  288.  *   feedback_polygon - when rendering mode is GL_FEEDBACK
  289.  *   select_polygon - when rendering mode is GL_SELECT
  290.  *   flat_ci_polygon - flat-shaded, any raster ops, RGBA polygon
  291.  *   smooth_ci_polygon - smooth-shaded, any raster ops, CI polygon
  292.  *   flat_rgba_polygon - flat-shaded, any raster ops, RGBA polygon
  293.  *   smooth_rgba_polygon - smooth-shaded, any raster ops, RGBA polygon
  294.  *   textured_polygon - smooth-shaded, textured RGBA polygon
  295.  */
  296.  
  297.  
  298. /*
  299.  * All polygon drawing functions have the same arguments:
  300.  * n      - number of vertices
  301.  * vlist  - array of indexes into the vertex list
  302.  * pv     - provoking vertex: which vertex color to use for flat shading.
  303.  */
  304.  
  305.  
  306.  
  307. /*
  308.  * Evaluate the current polygon's plane equation at (x,y) to get Z.
  309.  */
  310. GLint gl_compute_z( GLfloat x, GLfloat y )
  311. {
  312.    GLfloat fz;
  313.  
  314.    fz = (CC.PlaneD - CC.PlaneA*x - CC.PlaneB*y) / CC.PlaneC;
  315.  
  316.    if (fz<0.0F) {
  317.       return 0;
  318.    }
  319.    else if (fz>1.0F) {
  320.       return MAX_DEPTH;
  321.    }
  322.  
  323.    return (GLint) (fz * DEPTH_SCALE);
  324. }
  325.  
  326.  
  327. /* This macro can't be used for now.  Sometimes the evaluation of the
  328.  * plane equation at (x,y) results in a z which is too large or small
  329.  * to store in an integer, causing a FP exception.  We check for this
  330.  * case in the above function.
  331.  
  332. #define gl_compute_z( X, Y )  \
  333.     ((CC.PlaneD - CC.PlaneA*(X) - CC.PlaneB*(Y)) / CC.PlaneC)
  334.  */
  335.  
  336.  
  337.  
  338.  
  339. /*
  340.  * Put polygon in feedback buffer.
  341.  */
  342. static void feedback_polygon( GLuint n, GLuint vlist[], GLuint pv )
  343. {
  344.    GLuint i;
  345.  
  346.    APPEND_TOKEN( (GLfloat) GL_POLYGON_TOKEN );
  347.    APPEND_TOKEN( (GLfloat) n );
  348.  
  349.    for (i=0;i<n;i++) {
  350.       GLfloat x, y, z, w;
  351.       GLfloat tc[4];
  352.       GLuint j = vlist[i];
  353.  
  354.       x = VB.Win[j][0];
  355.       y = VB.Win[j][1];
  356.       z = VB.Win[j][2];
  357.       w = VB.Clip[j][3];
  358.  
  359.       tc[0] = VB.TexCoord[j][0];
  360.       tc[1] = VB.TexCoord[j][1];
  361.       tc[2] = 0.0F;          /* TODO: R, Q components */
  362.       tc[3] = 1.0F;
  363.  
  364.       gl_feedback_vertex( x, y, z, w, VB.Color[j], VB.Index[j], tc );
  365.    }
  366. }
  367.  
  368.  
  369.  
  370. /*
  371.  * Put polygon in selection buffer.
  372.  */
  373. static void select_polygon( GLuint n, GLuint vlist[], GLuint pv )
  374. {
  375.    GLuint i;
  376.  
  377.    CC.HitFlag = GL_TRUE;
  378.    for (i=0;i<n;i++) {
  379.       GLuint j = vlist[i];
  380.       GLfloat wz = VB.Win[j][2];
  381.       if (wz < CC.HitMinZ) {
  382.      CC.HitMinZ = wz;
  383.       }
  384.       if (wz > CC.HitMaxZ) {
  385.      CC.HitMaxZ = wz;
  386.       }
  387.    }
  388. }
  389.  
  390.  
  391.  
  392. /* Max number of pixels along a polygon's edge */
  393. #if MAX_WIDTH > MAX_HEIGHT
  394. #  define EDGEMAX MAX_WIDTH
  395. #else
  396. #  define EDGEMAX MAX_HEIGHT
  397. #endif
  398.  
  399.  
  400. /*
  401.  * Left and right boundary values for polygon scan conversion
  402.  */
  403. static GLfloat flx[MAX_HEIGHT], frx[MAX_HEIGHT];/* X bounds */
  404. static GLint li[MAX_HEIGHT], ri[MAX_HEIGHT];    /* Color Index */
  405. static GLint lr[MAX_HEIGHT], rr[MAX_HEIGHT];    /* Red */
  406. static GLint lg[MAX_HEIGHT], rg[MAX_HEIGHT];    /* Green */
  407. static GLint lb[MAX_HEIGHT], rb[MAX_HEIGHT];    /* Blue */
  408. static GLint la[MAX_HEIGHT], ra[MAX_HEIGHT];    /* Alpha */
  409. static GLfloat ls[MAX_HEIGHT], rs[MAX_HEIGHT];    /* S */
  410. static GLfloat lt[MAX_HEIGHT], rt[MAX_HEIGHT];    /* T */
  411.  
  412.  
  413.  
  414. #ifdef LEAVEOUT
  415. /* THIS IS EXPERIMENTAL, NOT USED. */
  416. void gl_setup_edge( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
  417.                     GLfloat *x0, GLfloat *dx,
  418.                     GLint *ymin, GLint *ymax, GLint *dy )
  419. {
  420.    GLfloat fy, slope;
  421.  
  422.    if (y1==y2) {
  423.       /* skip horizontal edges */
  424.       *ymin = *ymax = 0;
  425.       return;
  426.    }
  427.  
  428.    *dx = slope = (x2-x1) / (y2-y1);
  429.  
  430.    if (y1<y2) {
  431.       *ymin = (int) (y1 + 0.5F);
  432.       *ymax = (int) (y2 + 0.5F) - 0;  /* ADD one? */
  433.       fy = *ymin + 0.5F - y1;
  434.       *x0 = x1 + fy * slope;
  435.       *dy = 1;
  436.    }
  437.    else {
  438.       *ymin = (int) (y2 + 0.5F);
  439.       *ymax = (int) (y1 + 0.5F) - 0;  /* ADD one? */
  440.       fy = *ymax + 0.5F - y1;
  441.       *x0 = x1 + fy * slope;
  442.       *dx = -slope;
  443.       *dy = 1;
  444.    }
  445. }
  446. #endif
  447.  
  448.  
  449. /*
  450.  * Compute the location of the pixels along the edge of a polygon.
  451.  * Input:  x1,y1, x2,y2 - endpoints of the polygon edge
  452.  * Output:  x, y - array of edge coords
  453.  * Return:  number of elements in x[], and y[]
  454.  */
  455. #ifdef LEAVEOUT
  456. /* This version should be faster but unfortunately introduces a sampling bug */
  457. GLuint gl_polygon_edge( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
  458.                         GLfloat x[], GLint y[])
  459. {
  460.    GLint ymin, ymax, iy;
  461.    GLfloat slope, fx, fy;
  462.    GLuint n;
  463.  
  464.    if (y1==y2) {
  465.       /* skip horizontal edges */
  466.       return 0;
  467.    }
  468.  
  469.    slope = (x2-x1) / (y2-y1);
  470.    n = 0;
  471.    if (y1<y2) {
  472.       ymin = (int) (y1 + 0.5F);
  473.       ymax = (int) (y2 + 0.5F) - 1;
  474.       fy = ymin + 0.5F - y1;
  475.       fx = x1 + fy * slope;
  476.       for (iy=ymin; iy<=ymax; iy++, fx+=slope, n++) {
  477.      x[n] = fx;
  478.      y[n] = iy;
  479.       }
  480.    }
  481.    else {
  482.       ymin = (int) (y2 + 0.5F);
  483.       ymax = (int) (y1 + 0.5F) - 1;
  484.       fy = ymax + 0.5F - y1;
  485.       fx = x1 + fy * slope;
  486.       for (iy=ymax; iy>=ymin; iy--, fx-=slope, n++) {
  487.      x[n] = fx;
  488.      y[n] = iy;
  489.       }
  490.    }
  491.    return n;
  492. }
  493. #else
  494. /* this versions works but isn't the most efficient */
  495. GLuint gl_polygon_edge( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2,
  496.                             GLfloat x[], GLint y[])
  497. {
  498.    GLint ymin, ymax, iy;
  499.    GLfloat slope;
  500.    GLuint i;
  501.  
  502.    if (y1==y2) {
  503.       /* skip horizontal edges */
  504.       return 0;
  505.    }
  506.  
  507.    slope = (x2-x1) / (y2-y1);
  508.    i = 0;
  509.  
  510.    if (y1<y2) {
  511.       ymin = (int) (y1 + 0.5F);
  512.       ymax = (int) (y2 + 0.5F) - 1;
  513.       for (iy=ymin; iy<=ymax; iy++) {
  514.          x[i] = x1 + ((iy+0.5F) - y1) * slope;
  515.          y[i] = iy;
  516.          i++;
  517.       }
  518.    }
  519.    else {
  520.       ymin = (int) (y2 + 0.5F);
  521.       ymax = (int) (y1 + 0.5F) - 1;
  522.       for (iy=ymax; iy>=ymin; iy--) {
  523.          x[i] = x1 + ((iy+0.5F) - y1) * slope;
  524.          y[i] = iy;
  525.          i++;
  526.       }
  527.    }
  528.    return i;
  529. }
  530.  
  531. #endif
  532.  
  533.  
  534.  
  535. static void flat_ci_polygon( GLuint n, GLuint vlist[], GLuint pv )
  536. {
  537.    GLint i, j, y;
  538.    GLint ymin, ymax;
  539.    GLuint index;
  540.  
  541.    /* find min and max of window coordinate Y values */
  542.    {
  543.       GLfloat min = 1.0e10;
  544.       GLfloat max = -1.0e10;
  545.       if (n==3) {
  546.          GLfloat winy;
  547.          winy = VB.Win[vlist[0]][1];
  548.          if (winy > max)  max = winy;
  549.          if (winy < min)  min = winy;
  550.          winy = VB.Win[vlist[1]][1];
  551.          if (winy > max)  max = winy;
  552.          if (winy < min)  min = winy;
  553.          winy = VB.Win[vlist[2]][1];
  554.          if (winy > max)  max = winy;
  555.          if (winy < min)  min = winy;
  556.       }
  557.       else {
  558.          for (i=0;i<n;i++) {
  559.             GLfloat winy = VB.Win[vlist[i]][1];
  560.             if (winy > max)  max = winy;
  561.             if (winy < min)  min = winy;
  562.          }
  563.       }
  564.       ymin = (GLint) min;
  565.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  566.       ymax = (GLint) max;
  567.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  568.    }
  569.  
  570.    /* init edge bounds */
  571.    for (y=ymin;y<=ymax;y++) {
  572.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  573.       frx[y] = -1.0;
  574.    }
  575.  
  576.    /* process edges to compute span bounds */
  577.    for (i=0;i<n;i++) {
  578.       GLuint j0, j1, len;
  579.       GLfloat ex[EDGEMAX];
  580.       GLint ey[EDGEMAX];
  581.  
  582.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  583.       j1 = vlist[i];
  584.  
  585.       /* compute edge pixels */
  586.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  587.                              VB.Win[j1][0], VB.Win[j1][1],
  588.                              ex, ey );
  589.  
  590.       /* update bounds */
  591.       for (j=0;j<len;j++) {
  592.      GLfloat x = ex[j];
  593.      GLint y = ey[j];
  594.  
  595.      if (y>=0 && y<MAX_HEIGHT) {
  596.         if (x<flx[y]) {
  597.            flx[y] = x;
  598.         }
  599.         if (x>frx[y]) {
  600.            frx[y] = x;
  601.         }
  602.      }
  603.       }
  604.    }
  605.  
  606.    if (!VB.MonoColor) {
  607.       /* set the color index */
  608.       index = (GLuint) (GLint) VB.Index[pv];
  609.       (*DD.index)( index );
  610.    }
  611.  
  612.    /* process spans */
  613.    /* TODO: don't always have to compute pixel depths! */
  614.    for (y=ymin;y<=ymax;y++) {
  615.       GLint xmin = (GLint) (flx[y] + 0.5);
  616.       GLint xmax = (GLint) (frx[y] - 0.5);
  617.       GLint len = xmax-xmin+1;
  618.       if (len>0) {
  619.      GLint z0, z1;
  620.      GLint zspan[MAX_WIDTH];
  621.  
  622.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  623.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  624.      gl_interpolate_i( len, z0, z1, zspan );
  625.  
  626.      gl_write_monoindex_span( len, xmin, y, zspan, index, GL_POLYGON );
  627.       }
  628.    }
  629. }
  630.  
  631.  
  632.  
  633. static void smooth_ci_polygon( GLuint n, GLuint vlist[], GLuint pv )
  634. {
  635.    GLint i, j, y;
  636.    GLint ymin, ymax;
  637.  
  638.    /* find min and max of window coordinate Y values */
  639.    {
  640.       GLfloat min = 1.0e10;
  641.       GLfloat max = -1.0e10;
  642.       if (n==3) {
  643.          GLfloat winy;
  644.          winy = VB.Win[vlist[0]][1];
  645.          if (winy > max)  max = winy;
  646.          if (winy < min)  min = winy;
  647.          winy = VB.Win[vlist[1]][1];
  648.          if (winy > max)  max = winy;
  649.          if (winy < min)  min = winy;
  650.          winy = VB.Win[vlist[2]][1];
  651.          if (winy > max)  max = winy;
  652.          if (winy < min)  min = winy;
  653.       }
  654.       else {
  655.          for (i=0;i<n;i++) {
  656.             GLfloat winy = VB.Win[vlist[i]][1];
  657.             if (winy > max)  max = winy;
  658.             if (winy < min)  min = winy;
  659.          }
  660.       }
  661.       ymin = (GLint) min;
  662.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  663.       ymax = (GLint) max;
  664.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  665.    }
  666.  
  667.    /* init edge bounds */
  668.    for (y=ymin;y<=ymax;y++) {
  669.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  670.       frx[y] = -1.0;
  671.    }
  672.  
  673.    /* process edges to compute bounds */
  674.    for (i=0;i<n;i++) {
  675.       GLuint j0, j1, len;
  676.       GLfloat ex[EDGEMAX];
  677.       GLint ey[EDGEMAX];
  678.       GLuint ei[EDGEMAX];
  679.  
  680.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  681.       j1 = vlist[i];
  682.  
  683.       /* compute edge pixels */
  684.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  685.                              VB.Win[j1][0], VB.Win[j1][1],
  686.                              ex, ey );
  687.  
  688.       /* interpolate index along edge */
  689.       gl_interpolate_i( len,
  690.                 (GLint) VB.Index[j0], (GLint) VB.Index[j1],
  691.                 (GLint *) ei );
  692.  
  693.       /* update bounds */
  694.       for (j=0;j<len;j++) {
  695.      GLfloat x = ex[j];
  696.      GLint y = ey[j];
  697.  
  698.      if (y>=0 && y<MAX_DEPTH) {
  699.         if (x < flx[y]) {
  700.            flx[y] = x;
  701.            li[y] = ei[j];
  702.         }
  703.         if (x > frx[y]) {
  704.            frx[y] = x;
  705.            ri[y] = ei[j];
  706.         }
  707.      }
  708.       }
  709.    }
  710.  
  711.    /* process spans */
  712.    for (y=ymin;y<=ymax;y++) {
  713.       GLint xmin = (GLint) (flx[y] + 0.5);
  714.       GLint xmax = (GLint) (frx[y] - 0.5);
  715.       GLint len = xmax-xmin+1;
  716.       if (len>0) {
  717.      GLint z0, z1;
  718.      GLint zspan[MAX_WIDTH];
  719.      GLuint index[MAX_WIDTH];
  720.  
  721.      /* interpolate z and index along span */
  722.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  723.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  724.      gl_interpolate_i( len, z0, z1, zspan );
  725.      gl_interpolate_i( len, li[y], ri[y], (GLint *) index );
  726.  
  727.      gl_write_index_span( len, xmin, y, zspan, index, GL_POLYGON );
  728.       }
  729.    }
  730. }
  731.  
  732.  
  733.  
  734. static void flat_rgba_polygon( GLuint n, GLuint vlist[], GLuint pv )
  735. {
  736.    GLint i, j, y;
  737.    GLint ymin, ymax;
  738.  
  739.    /* find min and max of window coordinate Y values */
  740.    {
  741.       GLfloat min = 1.0e10;
  742.       GLfloat max = -1.0e10;
  743.       if (n==3) {
  744.          GLfloat winy;
  745.          winy = VB.Win[vlist[0]][1];
  746.          if (winy > max)  max = winy;
  747.          if (winy < min)  min = winy;
  748.          winy = VB.Win[vlist[1]][1];
  749.          if (winy > max)  max = winy;
  750.          if (winy < min)  min = winy;
  751.          winy = VB.Win[vlist[2]][1];
  752.          if (winy > max)  max = winy;
  753.          if (winy < min)  min = winy;
  754.       }
  755.       else {
  756.          for (i=0;i<n;i++) {
  757.             GLfloat winy = VB.Win[vlist[i]][1];
  758.             if (winy > max)  max = winy;
  759.             if (winy < min)  min = winy;
  760.          }
  761.       }
  762.       ymin = (GLint) min;
  763.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  764.       ymax = (GLint) max;
  765.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  766.    }
  767.  
  768.    /* init edge bounds */
  769.    for (y=ymin;y<=ymax;y++) {
  770.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  771.       frx[y] = -1.0;
  772.    }
  773.  
  774.    /* process edges to compute span bounds */
  775.    for (i=0;i<n;i++) {
  776.       GLuint j0, j1, len;
  777.       GLfloat ex[EDGEMAX];
  778.       GLint ey[EDGEMAX];
  779.  
  780.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  781.       j1 = vlist[i];
  782.  
  783.       /* compute edge pixels */
  784.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  785.                              VB.Win[j1][0], VB.Win[j1][1],
  786.                              ex, ey );
  787.  
  788.       /* update bounds */
  789.       for (j=0;j<len;j++) {
  790.      GLfloat x = ex[j];
  791.      GLint y = ey[j];
  792.  
  793.      if (y>=0 && y<MAX_HEIGHT) {
  794.         if (x<flx[y]) {
  795.            flx[y] = x;
  796.         }
  797.         if (x>frx[y]) {
  798.            frx[y] = x;
  799.         }
  800.      }
  801.       }
  802.    }
  803.  
  804.    if (!VB.MonoColor) {
  805.       /* set the color */
  806.       GLubyte r = (GLint) (VB.Color[pv][0] * CC.RedScale);
  807.       GLubyte g = (GLint) (VB.Color[pv][1] * CC.GreenScale);
  808.       GLubyte b = (GLint) (VB.Color[pv][2] * CC.BlueScale);
  809.       GLubyte a = (GLint) (VB.Color[pv][3] * CC.AlphaScale);
  810.       if (CC.RasterMask & GAMMA_BIT) {
  811.          gl_apply_gamma( 1, &r, &g, &b );
  812.       }
  813.       (*DD.color)( r, g, b,a );
  814.    }
  815.  
  816.    /* process spans */
  817.    /* TODO: don't always have to compute pixel depths! */
  818.    for (y=ymin;y<=ymax;y++) {
  819.       GLint xmin = (GLint) (flx[y] + 0.5);
  820.       GLint xmax = (GLint) (frx[y] - 0.5);
  821.       GLint len = xmax-xmin+1;
  822.       if (len>0) {
  823.      GLint z0, z1;
  824.      GLint zspan[MAX_WIDTH];
  825.  
  826.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  827.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  828.      gl_interpolate_i( len, z0, z1, zspan );
  829.  
  830.      gl_write_monocolor_span( len, xmin, y, zspan, VB.Color[pv],
  831.                   GL_POLYGON );
  832.       }
  833.    }
  834. }
  835.  
  836.  
  837.  
  838.  
  839. static void smooth_rgba_polygon( GLuint n, GLuint vlist[], GLuint pv )
  840. {
  841.    GLint i, j, y;
  842.    GLint ymin, ymax;
  843.  
  844.    /* find min and max of window coordinate Y values */
  845.    {
  846.       GLfloat min = 1.0e10;
  847.       GLfloat max = -1.0e10;
  848.       if (n==3) {
  849.          GLfloat winy;
  850.          winy = VB.Win[vlist[0]][1];
  851.          if (winy > max)  max = winy;
  852.          if (winy < min)  min = winy;
  853.          winy = VB.Win[vlist[1]][1];
  854.          if (winy > max)  max = winy;
  855.          if (winy < min)  min = winy;
  856.          winy = VB.Win[vlist[2]][1];
  857.          if (winy > max)  max = winy;
  858.          if (winy < min)  min = winy;
  859.       }
  860.       else {
  861.          for (i=0;i<n;i++) {
  862.             GLfloat winy = VB.Win[vlist[i]][1];
  863.             if (winy > max)  max = winy;
  864.             if (winy < min)  min = winy;
  865.          }
  866.       }
  867.       ymin = (GLint) min;
  868.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  869.       ymax = (GLint) max;
  870.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  871.    }
  872.  
  873.    /* init edge bounds */
  874.    for (y=ymin;y<=ymax;y++) {
  875.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  876.       frx[y] = -1.0;
  877.    }
  878.  
  879.    /* process edges to compute bounds */
  880.    for (i=0;i<n;i++) {
  881.       GLuint j0, j1, len;
  882.       GLfloat ex[EDGEMAX];
  883.       GLint ey[EDGEMAX];
  884.       GLint r0, g0, b0, a0, r1, g1, b1, a1, dr, dg, db, da;
  885.  
  886.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  887.       j1 = vlist[i];
  888.  
  889.       /* compute edge pixels */
  890.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  891.                              VB.Win[j1][0], VB.Win[j1][1],
  892.                              ex, ey );
  893.  
  894.       /* setup for edge color interpolation */
  895.       r0 = (GLint) (VB.Color[j0][0] * CC.RedScale) << 8;
  896.       r1 = (GLint) (VB.Color[j1][0] * CC.RedScale) << 8;
  897.       g0 = (GLint) (VB.Color[j0][1] * CC.GreenScale) << 8;
  898.       g1 = (GLint) (VB.Color[j1][1] * CC.GreenScale) << 8;
  899.       b0 = (GLint) (VB.Color[j0][2] * CC.BlueScale) << 8;
  900.       b1 = (GLint) (VB.Color[j1][2] * CC.BlueScale) << 8;
  901.       a0 = (GLint) (VB.Color[j0][3] * CC.AlphaScale) << 8;
  902.       a1 = (GLint) (VB.Color[j1][3] * CC.AlphaScale) << 8;
  903.       if (len>1) {
  904.          GLint n = len-1;
  905.          dr = (r1-r0) / n;
  906.          dg = (g1-g0) / n;
  907.          db = (b1-b0) / n;
  908.          da = (a1-a0) / n;
  909.       }
  910.       else {
  911.          dr = dg = db = da = 0;
  912.       }
  913.  
  914.       /* update span bounds */
  915.       for (j=0;j<len;j++) {
  916.      GLfloat x = ex[j];
  917.      GLint y = ey[j];
  918.  
  919.      if (y>=0 && y<MAX_HEIGHT) {
  920.         if (x < flx[y]) {
  921.            flx[y] = x;
  922.            lr[y] = r0 >> 8;
  923.            lg[y] = g0 >> 8;
  924.            lb[y] = b0 >> 8;
  925.            la[y] = a0 >> 8;
  926.         }
  927.         if (x > frx[y]) {
  928.            frx[y] = x;
  929.            rr[y] = r0 >> 8;
  930.            rg[y] = g0 >> 8;
  931.            rb[y] = b0 >> 8;
  932.            ra[y] = a0 >> 8;
  933.         }
  934.      }
  935.          r0 += dr;   g0 += dg;   b0 += db;   a0 += da;
  936.       }
  937.    }
  938.  
  939.    /* process spans */
  940.    for (y=ymin;y<=ymax;y++) {
  941.       GLint xmin = (GLint) (flx[y] + 0.5);
  942.       GLint xmax = (GLint) (frx[y] - 0.5);
  943.       GLint len = xmax-xmin+1;
  944.       if (len>0) {
  945.      GLint z0, z1;
  946.      GLint zspan[MAX_WIDTH];
  947.      GLubyte red[MAX_WIDTH];
  948.      GLubyte green[MAX_WIDTH];
  949.      GLubyte blue[MAX_WIDTH];
  950.      GLubyte alpha[MAX_WIDTH];
  951.  
  952.      /* interpolate z and colors */
  953.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  954.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  955.      GL_INTERPOLATE_I( len, z0, z1, zspan );
  956.          GL_INTERPOLATE_4UB( len,
  957.                              lr[y], rr[y], red,
  958.                              lg[y], rg[y], green,
  959.                              lb[y], rb[y], blue,
  960.                              la[y], ra[y], alpha );
  961.  
  962.      gl_write_color_span( len, xmin, y, zspan,
  963.                   red, green, blue, alpha, GL_POLYGON );
  964.       }
  965.    }
  966. }
  967.  
  968.  
  969.  
  970. /*
  971.  * This is a very special case function:  RGBA mode, flat shaded,
  972.  * depth buffered (GL_LESS) polygon.
  973.  */
  974. static void fast_flat_rgba_z_polygon( GLuint n, GLuint vlist[], GLuint pv )
  975. {
  976.    GLint i, j, y;
  977.    GLint ymin, ymax;
  978.  
  979.    /* find min and max of window coordinate Y values */
  980.    {
  981.       GLfloat min = 1.0e10;
  982.       GLfloat max = -1.0e10;
  983.       if (n==3) {
  984.          GLfloat winy;
  985.          winy = VB.Win[vlist[0]][1];
  986.          if (winy > max)  max = winy;
  987.          if (winy < min)  min = winy;
  988.          winy = VB.Win[vlist[1]][1];
  989.          if (winy > max)  max = winy;
  990.          if (winy < min)  min = winy;
  991.          winy = VB.Win[vlist[2]][1];
  992.          if (winy > max)  max = winy;
  993.          if (winy < min)  min = winy;
  994.       }
  995.       else {
  996.          for (i=0;i<n;i++) {
  997.             GLfloat winy = VB.Win[vlist[i]][1];
  998.             if (winy > max)  max = winy;
  999.             if (winy < min)  min = winy;
  1000.          }
  1001.       }
  1002.       ymin = (GLint) min;
  1003.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  1004.       ymax = (GLint) max;
  1005.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  1006.    }
  1007.  
  1008.    /* init edge bounds */
  1009.    for (y=ymin;y<=ymax;y++) {
  1010.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  1011.       frx[y] = -1.0;
  1012.    }
  1013.  
  1014.    if (!VB.MonoColor) {
  1015.       /* set the color */
  1016.       GLubyte r = (GLint) (VB.Color[pv][0] * CC.RedScale);
  1017.       GLubyte g = (GLint) (VB.Color[pv][1] * CC.GreenScale);
  1018.       GLubyte b = (GLint) (VB.Color[pv][2] * CC.BlueScale);
  1019.       GLubyte a = (GLint) (VB.Color[pv][3] * CC.AlphaScale);
  1020.       if (CC.RasterMask & GAMMA_BIT) {
  1021.          gl_apply_gamma( 1, &r, &g, &b );
  1022.       }
  1023.       (*DD.color)( r, g, b,a );
  1024.    }
  1025.  
  1026.    /* process edges to compute bounds */
  1027.    for (i=0;i<n;i++) {
  1028.       GLuint j0, j1, len;
  1029.       GLfloat ex[EDGEMAX];
  1030.       GLint ey[EDGEMAX];
  1031.  
  1032.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  1033.       j1 = vlist[i];
  1034.  
  1035.       /* compute edge pixels */
  1036.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  1037.                              VB.Win[j1][0], VB.Win[j1][1],
  1038.                              ex, ey );
  1039.  
  1040.       /* update span bounds */
  1041.       for (j=0;j<len;j++) {
  1042.      GLfloat x = ex[j];
  1043.      GLint y = ey[j];
  1044.      if (y>=0 && y<MAX_HEIGHT) {
  1045.         if (x < flx[y]) {
  1046.            flx[y] = x;
  1047.         }
  1048.         if (x > frx[y]) {
  1049.            frx[y] = x;
  1050.         }
  1051.      }
  1052.       }
  1053.    }
  1054.  
  1055.    /* process spans */
  1056.    for (y=ymin;y<=ymax;y++) {
  1057.       GLint xmin = (GLint) (flx[y] + 0.5);
  1058.       GLint xmax = (GLint) (frx[y] - 0.5);
  1059.       GLint len = xmax-xmin+1;
  1060.       if (len>0) {
  1061.      GLint zspan[MAX_WIDTH];
  1062.      GLubyte mask[MAX_WIDTH];
  1063.      GLint z0, z1, *zptr;
  1064.          GLuint passed = 0;
  1065.  
  1066.      /* interpolate z */
  1067.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  1068.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  1069.      GL_INTERPOLATE_I( len, z0, z1, zspan );
  1070.  
  1071.      /* do depth test */
  1072.      zptr = CC.DepthBuffer + y * CC.BufferWidth + xmin;
  1073.      for (i=0;i<len;i++) {
  1074.         if (zspan[i]<zptr[i]) {
  1075.            zptr[i] = zspan[i];
  1076.            mask[i] = 1;
  1077.                passed++;
  1078.         }
  1079.         else {
  1080.            mask[i] = 0;
  1081.         }
  1082.      }
  1083.      /* write pixels */
  1084.          if (passed>0) {
  1085.             (*DD.write_monocolor_span)( len, xmin, y, mask );
  1086.          }
  1087.       }
  1088.    }
  1089. }
  1090.  
  1091.  
  1092.  
  1093. /*
  1094.  * This is a very special case function:  RGBA mode, smooth shaded,
  1095.  * depth buffered (GL_LESS) polygon.
  1096.  */
  1097. static void fast_smooth_rgba_z_polygon( GLuint n, GLuint vlist[], GLuint pv )
  1098. {
  1099.    GLint i, j, y;
  1100.    GLint ymin, ymax;
  1101.  
  1102.    /* find min and max of window coordinate Y values */
  1103.    {
  1104.       GLfloat min = 1.0e10;
  1105.       GLfloat max = -1.0e10;
  1106.       if (n==3) {
  1107.          GLfloat winy;
  1108.          winy = VB.Win[vlist[0]][1];
  1109.          if (winy > max)  max = winy;
  1110.          if (winy < min)  min = winy;
  1111.          winy = VB.Win[vlist[1]][1];
  1112.          if (winy > max)  max = winy;
  1113.          if (winy < min)  min = winy;
  1114.          winy = VB.Win[vlist[2]][1];
  1115.          if (winy > max)  max = winy;
  1116.          if (winy < min)  min = winy;
  1117.       }
  1118.       else {
  1119.          for (i=0;i<n;i++) {
  1120.             GLfloat winy = VB.Win[vlist[i]][1];
  1121.             if (winy > max)  max = winy;
  1122.             if (winy < min)  min = winy;
  1123.          }
  1124.       }
  1125.       ymin = (GLint) min;
  1126.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  1127.       ymax = (GLint) max;
  1128.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  1129.    }
  1130.  
  1131.    /* init edge bounds */
  1132.    for (y=ymin;y<=ymax;y++) {
  1133.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  1134.       frx[y] = -1.0;
  1135.    }
  1136.  
  1137.    /* process edges to compute bounds */
  1138.    for (i=0;i<n;i++) {
  1139.       GLuint j0, j1, len;
  1140.       GLfloat ex[EDGEMAX];
  1141.       GLint ey[EDGEMAX];
  1142.       GLint r0, g0, b0, a0, r1, g1, b1, a1, dr, dg, db, da;
  1143.  
  1144.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  1145.       j1 = vlist[i];
  1146.  
  1147.       /* compute edge pixels */
  1148.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  1149.                              VB.Win[j1][0], VB.Win[j1][1],
  1150.                              ex, ey );
  1151.  
  1152.       /* interpolate colors along edge */
  1153.       r0 = (GLint) (VB.Color[j0][0] * CC.RedScale) << 8;
  1154.       r1 = (GLint) (VB.Color[j1][0] * CC.RedScale) << 8;
  1155.       g0 = (GLint) (VB.Color[j0][1] * CC.GreenScale) << 8;
  1156.       g1 = (GLint) (VB.Color[j1][1] * CC.GreenScale) << 8;
  1157.       b0 = (GLint) (VB.Color[j0][2] * CC.BlueScale) << 8;
  1158.       b1 = (GLint) (VB.Color[j1][2] * CC.BlueScale) << 8;
  1159.       a0 = (GLint) (VB.Color[j0][3] * CC.AlphaScale) << 8;
  1160.       a1 = (GLint) (VB.Color[j1][3] * CC.AlphaScale) << 8;
  1161.       if (len>1) {
  1162.          GLint n = len-1;
  1163.          dr = (r1-r0) / n;
  1164.          dg = (g1-g0) / n;
  1165.          db = (b1-b0) / n;
  1166.          da = (a1-a0) / n;
  1167.       }
  1168.       else {
  1169.          dr = dg = db = da = 0;
  1170.       }
  1171.  
  1172.       /* update span bounds */
  1173.       for (j=0;j<len;j++) {
  1174.      GLfloat x = ex[j];
  1175.      GLint y = ey[j];
  1176.      if (y>=0 && y<MAX_HEIGHT) {
  1177.         if (x < flx[y]) {
  1178.            flx[y] = x;
  1179.            lr[y] = r0 >> 8;
  1180.            lg[y] = g0 >> 8;
  1181.            lb[y] = b0 >> 8;
  1182.            la[y] = a0 >> 8;
  1183.         }
  1184.         if (x > frx[y]) {
  1185.            frx[y] = x;
  1186.            rr[y] = r0 >> 8;
  1187.            rg[y] = g0 >> 8;
  1188.            rb[y] = b0 >> 8;
  1189.            ra[y] = a0 >> 8;
  1190.         }
  1191.      }
  1192.          r0 += dr;   g0 += dg;   b0 += db;   a0 += da;
  1193.       }
  1194.    }
  1195.  
  1196.    /* process spans */
  1197.    for (y=ymin;y<=ymax;y++) {
  1198.       GLint xmin = (GLint) (flx[y] + 0.5);
  1199.       GLint xmax = (GLint) (frx[y] - 0.5);
  1200.       GLint len = xmax-xmin+1;
  1201.       if (len>0) {
  1202.      GLint zspan[MAX_WIDTH];
  1203.      GLubyte red[MAX_WIDTH];
  1204.      GLubyte green[MAX_WIDTH];
  1205.      GLubyte blue[MAX_WIDTH];
  1206.      GLubyte alpha[MAX_WIDTH];
  1207.      GLubyte mask[MAX_WIDTH];
  1208.      GLint z0, z1, *zptr;
  1209.          GLint r, g, b, a, dr, dg, db, da;
  1210.          GLuint passed = 0;
  1211.  
  1212.      /* interpolate z */
  1213.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  1214.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  1215.      GL_INTERPOLATE_I( len, z0, z1, zspan );
  1216.  
  1217.          /* setup for color interpolation */
  1218.          r = lr[y] << 8;
  1219.          g = lg[y] << 8;
  1220.          b = lb[y] << 8;
  1221.          a = la[y] << 8;
  1222.          if (len>1) {
  1223.             dr = ((rr[y] << 8) - r) / (len-1);
  1224.             dg = ((rg[y] << 8) - g) / (len-1);
  1225.             db = ((rb[y] << 8) - b) / (len-1);
  1226.             da = ((ra[y] << 8) - a) / (len-1);
  1227.          }
  1228.          else {
  1229.             dr = dg = db = da = 0;
  1230.          }
  1231.  
  1232.      /* do depth test */
  1233.      zptr = CC.DepthBuffer + y * CC.BufferWidth + xmin;
  1234.      for (i=0;i<len;i++) {
  1235.         if (zspan[i]<zptr[i]) {
  1236.            zptr[i] = zspan[i];
  1237.            mask[i] = 1;
  1238.                red[i]   = r >> 8;
  1239.                green[i] = g >> 8;
  1240.                blue[i]  = b >> 8;
  1241.                alpha[i] = a >> 8;
  1242.                passed++;
  1243.         }
  1244.         else {
  1245.            mask[i] = 0;
  1246.         }
  1247.             r += dr;  g += dg;  b += db;  a += da;
  1248.      }
  1249.      /* write pixels */
  1250.          if (passed>0) {
  1251.             (*DD.write_color_span)( len, xmin, y,
  1252.                                     red, green, blue, alpha, mask );
  1253.          }
  1254.       }
  1255.    }
  1256. }
  1257.  
  1258.  
  1259.  
  1260. static void textured_polygon( GLuint n, GLuint vlist[], GLuint pv )
  1261. {
  1262.    GLint i, j, y;
  1263.    GLint ymin, ymax;
  1264.    GLfloat leyez[MAX_HEIGHT], reyez[MAX_HEIGHT];
  1265.  
  1266.    /* find min and max of window coordinate Y values */
  1267.    {
  1268.       GLfloat min = 1.0e10;
  1269.       GLfloat max = -1.0e10;
  1270.       if (n==3) {
  1271.          GLfloat winy;
  1272.          winy = VB.Win[vlist[0]][1];
  1273.          if (winy > max)  max = winy;
  1274.          if (winy < min)  min = winy;
  1275.          winy = VB.Win[vlist[1]][1];
  1276.          if (winy > max)  max = winy;
  1277.          if (winy < min)  min = winy;
  1278.          winy = VB.Win[vlist[2]][1];
  1279.          if (winy > max)  max = winy;
  1280.          if (winy < min)  min = winy;
  1281.       }
  1282.       else {
  1283.          for (i=0;i<n;i++) {
  1284.             GLfloat winy = VB.Win[vlist[i]][1];
  1285.             if (winy > max)  max = winy;
  1286.             if (winy < min)  min = winy;
  1287.          }
  1288.       }
  1289.       ymin = (GLint) min;
  1290.       ymin = CLAMP( ymin, 0, MAX_HEIGHT-1 ) ;
  1291.       ymax = (GLint) max;
  1292.       ymax = CLAMP( ymax, 0, MAX_HEIGHT-1 ) ;
  1293.    }
  1294.  
  1295.    /* init edge bounds */
  1296.    for (y=ymin;y<=ymax;y++) {
  1297.       flx[y] = (GLfloat) (MAX_WIDTH+1);
  1298.       frx[y] = -1.0;
  1299.    }
  1300.  
  1301.    /* process edges to compute bounds */
  1302.    for (i=0;i<n;i++) {
  1303.       GLuint j0, j1, len;
  1304.       DEFARRAY( GLfloat, ex, EDGEMAX );  /* x in win coords */
  1305.       DEFARRAY( GLint, ey, EDGEMAX );    /* y in win coords */
  1306.       DEFARRAY( GLfloat, ez, EDGEMAX );  /* z in eye coords */
  1307.       DEFARRAY( GLfloat, es, EDGEMAX );  /* texture s,t */
  1308.       DEFARRAY( GLfloat, et, EDGEMAX );
  1309.       GLint r0, g0, b0, a0, r1, g1, b1, a1, dr, dg, db, da;
  1310.  
  1311.  
  1312.       j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  1313.       j1 = vlist[i];
  1314.  
  1315.       /* compute edge pixels */
  1316.       len = gl_polygon_edge( VB.Win[j0][0], VB.Win[j0][1],
  1317.                              VB.Win[j1][0], VB.Win[j1][1],
  1318.                              ex, ey );
  1319.  
  1320.       /* setup for edge color interpolation */
  1321.       r0 = (GLint) (VB.Color[j0][0] * CC.RedScale) << 8;
  1322.       r1 = (GLint) (VB.Color[j1][0] * CC.RedScale) << 8;
  1323.       g0 = (GLint) (VB.Color[j0][1] * CC.GreenScale) << 8;
  1324.       g1 = (GLint) (VB.Color[j1][1] * CC.GreenScale) << 8;
  1325.       b0 = (GLint) (VB.Color[j0][2] * CC.BlueScale) << 8;
  1326.       b1 = (GLint) (VB.Color[j1][2] * CC.BlueScale) << 8;
  1327.       a0 = (GLint) (VB.Color[j0][3] * CC.AlphaScale) << 8;
  1328.       a1 = (GLint) (VB.Color[j1][3] * CC.AlphaScale) << 8;
  1329.       if (len>1) {
  1330.          GLint n = len-1;
  1331.          dr = (r1-r0) / n;
  1332.          dg = (g1-g0) / n;
  1333.          db = (b1-b0) / n;
  1334.          da = (a1-a0) / n;
  1335.       }
  1336.       else {
  1337.          dr = dg = db = da = 0;
  1338.       }
  1339.  
  1340.       gl_interp_texcoords( len, VB.Eye[j0][2], VB.Eye[j1][2],
  1341.                VB.Win[j0][2] * MAX_DEPTH, VB.Win[j1][2] * MAX_DEPTH,
  1342.                VB.TexCoord[j0][0], VB.TexCoord[j1][0],
  1343.                            VB.TexCoord[j0][1], VB.TexCoord[j1][1],
  1344.                es, et, ez );
  1345.  
  1346.       /* update span bounds */
  1347.       for (j=0;j<len;j++) {
  1348.      register GLfloat x = ex[j];
  1349.      register GLint y = ey[j];
  1350.  
  1351.      if (y>=0 && y<MAX_HEIGHT) {
  1352.         /* update left and right span bounds */
  1353.         if (x < flx[y]) {
  1354.            flx[y] = x;
  1355.            lr[y] = r0 >> 8;
  1356.            lg[y] = g0 >> 8;
  1357.            lb[y] = b0 >> 8;
  1358.            la[y] = a0 >> 8;
  1359.            ls[y] = es[j];
  1360.            lt[y] = et[j];
  1361.            leyez[y] = ez[j];
  1362.         }
  1363.         if (x > frx[y]) {
  1364.            frx[y] = x;
  1365.            rr[y] = r0 >> 8;
  1366.            rg[y] = g0 >> 8;
  1367.            rb[y] = b0 >> 8;
  1368.            ra[y] = a0 >> 8;
  1369.            rs[y] = es[j];
  1370.            rt[y] = et[j];
  1371.            reyez[y] = ez[j];
  1372.         }
  1373.      }
  1374.          r0 += dr;   g0 += dg;   b0 += db;   a0 += da;
  1375.       }
  1376.       UNDEFARRAY( ex );
  1377.       UNDEFARRAY( ey );
  1378.       UNDEFARRAY( ez );
  1379.       UNDEFARRAY( es );
  1380.       UNDEFARRAY( et );
  1381.    }
  1382.  
  1383.    /* process spans */
  1384.    for (y=ymin;y<=ymax;y++) {
  1385.       GLint xmin = (GLint) (flx[y] + 0.5);
  1386.       GLint xmax = (GLint) (frx[y] - 0.5);
  1387.       GLint len = xmax-xmin+1;
  1388.       if (len>0) {
  1389.      GLint z0, z1;
  1390.      GLint zspan[MAX_WIDTH];
  1391.      GLubyte red[MAX_WIDTH];
  1392.      GLubyte green[MAX_WIDTH];
  1393.      GLubyte blue[MAX_WIDTH];
  1394.      GLubyte alpha[MAX_WIDTH];
  1395.      GLfloat s[MAX_WIDTH], t[MAX_WIDTH];
  1396.  
  1397.      /* interpolate z, colors and tex coords */
  1398.      z0 = gl_compute_z( flx[y]+0.5F, (GLfloat) y + 0.5F );
  1399.      z1 = gl_compute_z( frx[y]-0.5F, (GLfloat) y + 0.5F );
  1400.      GL_INTERPOLATE_I( len, z0, z1, zspan );
  1401.      GL_INTERPOLATE_4UB( len,
  1402.                              lr[y], rr[y], red,
  1403.                              lg[y], rg[y], green,
  1404.                              lb[y], rb[y], blue,
  1405.                              la[y], ra[y], alpha );
  1406.  
  1407.      gl_interp_texcoords( len, leyez[y], reyez[y],
  1408.                   (GLfloat) z0, (GLfloat) z1,
  1409.                   ls[y], rs[y], lt[y], rt[y],
  1410.                   s, t, NULL );
  1411.  
  1412.      gl_write_texture_span( len, xmin, y, zspan,  s, t,
  1413.                 red, green, blue, alpha, GL_POLYGON );
  1414.       }
  1415.    }
  1416. }
  1417.  
  1418.  
  1419.  
  1420.  
  1421. /*
  1422.  * Render a polygon whose front or back rendering modes are point or line.
  1423.  */
  1424. static void unfilled_polygon( GLuint n, GLuint vlist[], GLuint pv )
  1425. {
  1426.    GLuint i, j, j0, j1;
  1427.    GLuint facing = (VB.Color==VB.Bcolor);   /* 0=front, 1=back */
  1428.  
  1429.    CC.StippleCounter = 0;  /* in case we're drawing polygon outline */
  1430.  
  1431.    if (facing==0) {
  1432.       /* Front */
  1433.       if (CC.Polygon.FrontMode==GL_POINT) {
  1434.      for (i=0;i<n;i++) {
  1435.         j = vlist[i];
  1436.         if (VB.Edgeflag[j]) {
  1437.            (*CC.PointsFunc)( j, j );
  1438.         }
  1439.      }
  1440.       }
  1441.       else if (CC.Polygon.FrontMode==GL_LINE) {
  1442.      for (i=0;i<n;i++) {
  1443.         j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  1444.         j1 = vlist[i];
  1445.         if (VB.Edgeflag[j0]) {
  1446.            (*CC.LineFunc)( j0, j1, pv );
  1447.         }
  1448.      }
  1449.       }
  1450.       else {
  1451.      (*CC.AuxPolygonFunc)( n, vlist, pv );
  1452.       }
  1453.    }
  1454.    else {
  1455.       /* Back */
  1456.       if (CC.Polygon.BackMode==GL_POINT) {
  1457.      for (i=0;i<n;i++) {
  1458.         j = vlist[i];
  1459.         if (VB.Edgeflag[j]) {
  1460.            (*CC.PointsFunc)( j, j );
  1461.         }
  1462.      }
  1463.       }
  1464.       else if (CC.Polygon.BackMode==GL_LINE) {
  1465.      for (i=0;i<n;i++) {
  1466.         j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  1467.         j1 = vlist[i];
  1468.         if (VB.Edgeflag[j0]) {
  1469.            (*CC.LineFunc)( j0, j1, pv );
  1470.         }
  1471.      }
  1472.       }
  1473.       else {
  1474.      (*CC.AuxPolygonFunc)( n, vlist, pv );
  1475.       }
  1476.    }
  1477. }
  1478.  
  1479.  
  1480.  
  1481. /*
  1482.  * Determine which polygon rendering function to use given the current
  1483.  * rendering context.
  1484.  */
  1485. void gl_set_polygon_function( void )
  1486. {
  1487.    if (CC.RenderMode==GL_RENDER) {
  1488.       CC.PolygonFunc = (*DD.get_polygon_func)();
  1489.       if (CC.PolygonFunc) {
  1490.          /* Device Driver will draw the polygon */
  1491.       }
  1492.       else if (CC.Texture.Enabled) {
  1493.      /* textured */
  1494.      CC.PolygonFunc = textured_polygon;
  1495.       }
  1496.       else if (CC.RGBAflag
  1497.            && CC.Color.ColorMask==0xf
  1498.            && CC.RasterMask==DEPTH_BIT
  1499.            && CC.Depth.Func==GL_LESS
  1500.            && CC.Depth.Mask==GL_TRUE
  1501.            && CC.Polygon.StippleFlag==GL_FALSE
  1502.            && CC.Texture.Enabled==0
  1503.            && CC.ClipSpans==GL_FALSE) {
  1504.      /* Common cases */
  1505.          if (CC.Light.ShadeModel==GL_SMOOTH) {
  1506.             CC.PolygonFunc = fast_smooth_rgba_z_polygon;
  1507.          }
  1508.          else {
  1509.             CC.PolygonFunc = fast_flat_rgba_z_polygon;
  1510.          }
  1511.       }
  1512.       else {
  1513.      if (CC.Light.ShadeModel==GL_SMOOTH) {
  1514.         /* smooth shaded, no texturing, stippled or some raster ops */
  1515.         CC.PolygonFunc = CC.RGBAflag ? smooth_rgba_polygon : smooth_ci_polygon;
  1516.      }
  1517.      else {
  1518.         /* flat shaded, no texturing, stippled or some raster ops */
  1519.         CC.PolygonFunc = CC.RGBAflag ? flat_rgba_polygon : flat_ci_polygon;
  1520.      }
  1521.       }
  1522.  
  1523.       /* PolygonMode */
  1524.       if (CC.Polygon.Unfilled) {
  1525.      /* front or back are to be rendered as points or lines */
  1526.      if (!CC.PointsFunc) {
  1527.         gl_set_point_function();
  1528.      }
  1529.      if (!CC.LineFunc) {
  1530.         gl_set_line_function();
  1531.      }
  1532.      CC.AuxPolygonFunc = CC.PolygonFunc;
  1533.      CC.PolygonFunc = unfilled_polygon;
  1534.       }
  1535.    }
  1536.    else if (CC.RenderMode==GL_FEEDBACK) {
  1537.       CC.PolygonFunc = feedback_polygon;
  1538.    }
  1539.    else {
  1540.       /* GL_SELECT mode */
  1541.       CC.PolygonFunc = select_polygon;
  1542.    }
  1543. }
  1544.  
  1545.  
  1546.